package org.orbis.communicate.indexer.content;

import java.util.Comparator;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.locks.ReentrantLock;
import org.orbis.index.IndexingPackage;
import org.orbis.logging.LogParser;
import org.orbis.memorymanager.MemoryManager;
import org.orbis.structure.LookupPointer;

public class ContentIndexerClient implements Runnable{
	private static MemoryManager memman;
	private static PriorityBlockingQueue<IndexingPackage> clientQueue;
	private static Object clientBlockade;
	private static ReentrantLock indexLock;

	static{
		clientQueue =
			new PriorityBlockingQueue<IndexingPackage>(10, new Comparator<IndexingPackage>(){
				@Override
				public int compare(IndexingPackage o1, IndexingPackage o2){
					if(o1 == null || o2 == null) return 0;
					if(o1.ID() > o2.ID()) return 1;
					if(o1.ID() < o2.ID()) return -1;
					return 0;
				}
			});
		clientBlockade = new Object();
	}

	public ContentIndexerClient(boolean isCreateLog){}

	public static void property(MemoryManager manager){
		memman = manager;
		indexLock = new ReentrantLock();
	}

	public static void addToQueue(IndexingPackage newIndex){
		clientQueue.offer(newIndex);
	}

	public static boolean isEmpty(){
		return clientQueue.isEmpty();
	}

	public static void waitUntilEmpty(){
		if(!clientQueue.isEmpty()) try{
			clientBlockade.wait();
		}catch(InterruptedException e){}
	}

	public static int residue(){
		return clientQueue.size();
	}

	@Override
	public void run(){
		IndexingPackage newIndex = null;
		while(true){
			// Take from client queue
			try{
				newIndex = clientQueue.take();
				if(clientQueue.isEmpty()) synchronized(clientBlockade){
					clientBlockade.notifyAll();
				}
			}catch(InterruptedException e1){
				continue;
			}
			try{
				indexLock.lock();
				long startTime = LogParser.initTime();
				LookupPointer[] appPtr = new LookupPointer[newIndex.appendixLength()];
				for(int i = 0; i < newIndex.appendixLength(); i++)
					appPtr[i] =
						memman.storeAppendix(newIndex.appendix(i), newIndex.ID(), i, newIndex.cluster());
				startTime = LogParser.timerFinest("Index / Index appendix", startTime);
				for(int i = 0; i < newIndex.contentLength(); i++)
					memman.storeContent(newIndex.content(i), newIndex.ID(), i, appPtr, newIndex.cluster());
				startTime = LogParser.timerFinest("Index / Index content", startTime);
			}catch(Exception e){
				e.printStackTrace();
			}finally{
				indexLock.unlock();
			}
		}
	}
}
